package cn.gotom.svg.xml;

import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import android.graphics.Color;

/**
 * @author 裴绍国
 * @author <a href="mailto:peixere@gmail.com">裴绍国</a>
 */
public class ColorTable
{

	static final Map<String, Integer> colorTable;
	static
	{
		HashMap<String, Integer> table = new HashMap<String, Integer>();

		// We really should be interpreting the currentColor keyword as
		// a reference to the referring node's color, but this quick hack
		// will stop the program from crashing.
		table.put("currentcolor", Color.parseColor("#000000"));

		table.put("aliceblue", Color.parseColor("#f0f8ff"));
		table.put("antiquewhite", Color.parseColor("#faebd7"));
		table.put("aqua", Color.parseColor("#00ffff"));
		table.put("aquamarine", Color.parseColor("#7fffd4"));
		table.put("azure", Color.parseColor("#f0ffff"));
		table.put("beige", Color.parseColor("#f5f5dc"));
		table.put("bisque", Color.parseColor("#ffe4c4"));
		table.put("black", Color.parseColor("#000000"));
		table.put("blanchedalmond", Color.parseColor("#ffebcd"));
		table.put("blue", Color.parseColor("#0000ff"));
		table.put("blueviolet", Color.parseColor("#8a2be2"));
		table.put("brown", Color.parseColor("#a52a2a"));
		table.put("burlywood", Color.parseColor("#deb887"));
		table.put("cadetblue", Color.parseColor("#5f9ea0"));
		table.put("chartreuse", Color.parseColor("#7fff00"));
		table.put("chocolate", Color.parseColor("#d2691e"));
		table.put("coral", Color.parseColor("#ff7f50"));
		table.put("cornflowerblue", Color.parseColor("#6495ed"));
		table.put("cornsilk", Color.parseColor("#fff8dc"));
		table.put("crimson", Color.parseColor("#dc143c"));
		table.put("cyan", Color.parseColor("#00ffff"));
		table.put("darkblue", Color.parseColor("#00008b"));
		table.put("darkcyan", Color.parseColor("#008b8b"));
		table.put("darkgoldenrod", Color.parseColor("#b8860b"));
		table.put("darkgray", Color.parseColor("#a9a9a9"));
		table.put("darkgreen", Color.parseColor("#006400"));
		table.put("darkkhaki", Color.parseColor("#bdb76b"));
		table.put("darkmagenta", Color.parseColor("#8b008b"));
		table.put("darkolivegreen", Color.parseColor("#556b2f"));
		table.put("darkorange", Color.parseColor("#ff8c00"));
		table.put("darkorchid", Color.parseColor("#9932cc"));
		table.put("darkred", Color.parseColor("#8b0000"));
		table.put("darksalmon", Color.parseColor("#e9967a"));
		table.put("darkseagreen", Color.parseColor("#8fbc8f"));
		table.put("darkslateblue", Color.parseColor("#483d8b"));
		table.put("darkslategray", Color.parseColor("#2f4f4f"));
		table.put("darkturquoise", Color.parseColor("#00ced1"));
		table.put("darkviolet", Color.parseColor("#9400d3"));
		table.put("deeppink", Color.parseColor("#ff1493"));
		table.put("deepskyblue", Color.parseColor("#00bfff"));
		table.put("dimgray", Color.parseColor("#696969"));
		table.put("dodgerblue", Color.parseColor("#1e90ff"));
		table.put("feldspar", Color.parseColor("#d19275"));
		table.put("firebrick", Color.parseColor("#b22222"));
		table.put("floralwhite", Color.parseColor("#fffaf0"));
		table.put("forestgreen", Color.parseColor("#228b22"));
		table.put("fuchsia", Color.parseColor("#ff00ff"));
		table.put("gainsboro", Color.parseColor("#dcdcdc"));
		table.put("ghostwhite", Color.parseColor("#f8f8ff"));
		table.put("gold", Color.parseColor("#ffd700"));
		table.put("goldenrod", Color.parseColor("#daa520"));
		table.put("gray", Color.parseColor("#808080"));
		table.put("green", Color.parseColor("#008000"));
		table.put("greenyellow", Color.parseColor("#adff2f"));
		table.put("honeydew", Color.parseColor("#f0fff0"));
		table.put("hotpink", Color.parseColor("#ff69b4"));
		table.put("indianred", Color.parseColor("#cd5c5c"));
		table.put("indigo", Color.parseColor("#4b0082"));
		table.put("ivory", Color.parseColor("#fffff0"));
		table.put("khaki", Color.parseColor("#f0e68c"));
		table.put("lavender", Color.parseColor("#e6e6fa"));
		table.put("lavenderblush", Color.parseColor("#fff0f5"));
		table.put("lawngreen", Color.parseColor("#7cfc00"));
		table.put("lemonchiffon", Color.parseColor("#fffacd"));
		table.put("lightblue", Color.parseColor("#add8e6"));
		table.put("lightcoral", Color.parseColor("#f08080"));
		table.put("lightcyan", Color.parseColor("#e0ffff"));
		table.put("lightgoldenrodyellow", Color.parseColor("#fafad2"));
		table.put("lightgrey", Color.parseColor("#d3d3d3"));
		table.put("lightgreen", Color.parseColor("#90ee90"));
		table.put("lightpink", Color.parseColor("#ffb6c1"));
		table.put("lightsalmon", Color.parseColor("#ffa07a"));
		table.put("lightseagreen", Color.parseColor("#20b2aa"));
		table.put("lightskyblue", Color.parseColor("#87cefa"));
		table.put("lightslateblue", Color.parseColor("#8470ff"));
		table.put("lightslategray", Color.parseColor("#778899"));
		table.put("lightsteelblue", Color.parseColor("#b0c4de"));
		table.put("lightyellow", Color.parseColor("#ffffe0"));
		table.put("lime", Color.parseColor("#00ff00"));
		table.put("limegreen", Color.parseColor("#32cd32"));
		table.put("linen", Color.parseColor("#faf0e6"));
		table.put("magenta", Color.parseColor("#ff00ff"));
		table.put("maroon", Color.parseColor("#800000"));
		table.put("mediumaquamarine", Color.parseColor("#66cdaa"));
		table.put("mediumblue", Color.parseColor("#0000cd"));
		table.put("mediumorchid", Color.parseColor("#ba55d3"));
		table.put("mediumpurple", Color.parseColor("#9370d8"));
		table.put("mediumseagreen", Color.parseColor("#3cb371"));
		table.put("mediumslateblue", Color.parseColor("#7b68ee"));
		table.put("mediumspringgreen", Color.parseColor("#00fa9a"));
		table.put("mediumturquoise", Color.parseColor("#48d1cc"));
		table.put("mediumvioletred", Color.parseColor("#c71585"));
		table.put("midnightblue", Color.parseColor("#191970"));
		table.put("mintcream", Color.parseColor("#f5fffa"));
		table.put("mistyrose", Color.parseColor("#ffe4e1"));
		table.put("moccasin", Color.parseColor("#ffe4b5"));
		table.put("navajowhite", Color.parseColor("#ffdead"));
		table.put("navy", Color.parseColor("#000080"));
		table.put("oldlace", Color.parseColor("#fdf5e6"));
		table.put("olive", Color.parseColor("#808000"));
		table.put("olivedrab", Color.parseColor("#6b8e23"));
		table.put("orange", Color.parseColor("#ffa500"));
		table.put("orangered", Color.parseColor("#ff4500"));
		table.put("orchid", Color.parseColor("#da70d6"));
		table.put("palegoldenrod", Color.parseColor("#eee8aa"));
		table.put("palegreen", Color.parseColor("#98fb98"));
		table.put("paleturquoise", Color.parseColor("#afeeee"));
		table.put("palevioletred", Color.parseColor("#d87093"));
		table.put("papayawhip", Color.parseColor("#ffefd5"));
		table.put("peachpuff", Color.parseColor("#ffdab9"));
		table.put("peru", Color.parseColor("#cd853f"));
		table.put("pink", Color.parseColor("#ffc0cb"));
		table.put("plum", Color.parseColor("#dda0dd"));
		table.put("powderblue", Color.parseColor("#b0e0e6"));
		table.put("purple", Color.parseColor("#800080"));
		table.put("red", Color.parseColor("#ff0000"));
		table.put("rosybrown", Color.parseColor("#bc8f8f"));
		table.put("royalblue", Color.parseColor("#4169e1"));
		table.put("saddlebrown", Color.parseColor("#8b4513"));
		table.put("salmon", Color.parseColor("#fa8072"));
		table.put("sandybrown", Color.parseColor("#f4a460"));
		table.put("seagreen", Color.parseColor("#2e8b57"));
		table.put("seashell", Color.parseColor("#fff5ee"));
		table.put("sienna", Color.parseColor("#a0522d"));
		table.put("silver", Color.parseColor("#c0c0c0"));
		table.put("skyblue", Color.parseColor("#87ceeb"));
		table.put("slateblue", Color.parseColor("#6a5acd"));
		table.put("slategray", Color.parseColor("#708090"));
		table.put("snow", Color.parseColor("#fffafa"));
		table.put("springgreen", Color.parseColor("#00ff7f"));
		table.put("steelblue", Color.parseColor("#4682b4"));
		table.put("tan", Color.parseColor("#d2b48c"));
		table.put("teal", Color.parseColor("#008080"));
		table.put("thistle", Color.parseColor("#d8bfd8"));
		table.put("tomato", Color.parseColor("#ff6347"));
		table.put("turquoise", Color.parseColor("#40e0d0"));
		table.put("violet", Color.parseColor("#ee82ee"));
		table.put("violetred", Color.parseColor("#d02090"));
		table.put("wheat", Color.parseColor("#f5deb3"));
		table.put("white", Color.parseColor("#ffffff"));
		table.put("whitesmoke", Color.parseColor("#f5f5f5"));
		table.put("yellow", Color.parseColor("#ffff00"));
		table.put("yellowgreen", Color.parseColor("#9acd32"));

		colorTable = Collections.unmodifiableMap(table);
	}

	static ColorTable singleton = new ColorTable();

	/** Creates a new instance of ColorTable */
	protected ColorTable()
	{
		// buildColorList();
	}

	static public ColorTable instance()
	{
		return singleton;
	}

	public Integer lookupColor(String name)
	{
		return colorTable.get(name.toLowerCase(Locale.ROOT));
	}

	public static Integer parseColor(String val)
	{
		Integer retVal = null;

		if (val.charAt(0) == '#')
		{
			retVal = Color.parseColor(val);
		}
		else
		{
			final String number = "\\s*(((\\d+)(\\.\\d*)?)|(\\.\\d+))(%)?\\s*";
			final Matcher rgbMatch = Pattern.compile("rgb\\(" + number + "," + number + "," + number + "\\)", Pattern.CASE_INSENSITIVE).matcher("");

			rgbMatch.reset(val);
			if (rgbMatch.matches())
			{
				float rr = Float.parseFloat(rgbMatch.group(1));
				float gg = Float.parseFloat(rgbMatch.group(7));
				float bb = Float.parseFloat(rgbMatch.group(13));
				rr /= "%".equals(rgbMatch.group(6)) ? 100 : 255;
				gg /= "%".equals(rgbMatch.group(12)) ? 100 : 255;
				bb /= "%".equals(rgbMatch.group(18)) ? 100 : 255;
				retVal = Color.rgb((int) rr, (int) gg, (int) bb);
			}
			else
			{
				retVal = ColorTable.instance().lookupColor(val);
			}
		}

		return retVal;
	}

	public static int parseHex(String val)
	{
		int retVal = 0;

		for (int i = 0; i < val.length(); i++)
		{
			retVal <<= 4;

			char ch = val.charAt(i);
			if (ch >= '0' && ch <= '9')
			{
				retVal |= ch - '0';
			}
			else if (ch >= 'a' && ch <= 'z')
			{
				retVal |= ch - 'a' + 10;
			}
			else if (ch >= 'A' && ch <= 'Z')
			{
				retVal |= ch - 'A' + 10;
			}
			else
				throw new RuntimeException();
		}

		return retVal;
	}

}
